<?php

namespace app\common\service;

use app\common\exception\BusinessException;
use app\common\model\AppConfig;
use app\common\model\Sms;
use TencentCloud\Common\Credential;
use TencentCloud\Common\Profile\ClientProfile;
use TencentCloud\Common\Profile\HttpProfile;
use TencentCloud\Sms\V20210111\Models\SendSmsRequest;
use TencentCloud\Sms\V20210111\SmsClient;
use think\api\Client;

class SmsService
{

    /**
     * check
     * @param $mobile
     * @param $ip
     * @param string $openid
     * @throws
     */
    public function check($mobile, $ip, $openid = '')
    {
        // MB频率检测
        $time = time();
        $where = ['mobile' => $mobile];
        $info = app(Sms::class)->where($where)->order('a_time desc')->find();
        if ($info && ($time - $info['a_time']) < 60) {
            throw new BusinessException('请求频率过快');
        }

        // MB最大发送量检测
        $s_time = strtotime(date('Y-m-d 00:00:00'));
        $e_time = strtotime(date('Y-m-d 23:59:59'));
        $where = [
            ['mobile', '=', $mobile],
            ['a_time', 'between', [$s_time, $e_time]],
        ];
        $count = app(Sms::class)->where($where)->count();
        if ($count >= 5) {
            throw new BusinessException('请求量超过最大阈值');
        }

        // IP频率检测
        $time = time();
        $where = ['ip' => $ip];
        $info = app(Sms::class)->where($where)->order('a_time desc')->find();
        if ($info && ($time - $info['a_time']) < 60) {
            throw new BusinessException('请求频率过快');
        }

        // IP最大发送量检测
        $s_time = strtotime(date('Y-m-d 00:00:00'));
        $e_time = strtotime(date('Y-m-d 23:59:59'));
        $where = [
            ['ip', '=', $ip],
            ['a_time', 'between', [$s_time, $e_time]],
        ];
        $count = app(Sms::class)->where($where)->count();
        if ($count >= 5) {
            throw new BusinessException('请求量超过最大阈值');
        }

        // OpenId检测
        if ($openid) {

            // OpenId频率检测
            $where = ['openid' => $openid];
            $info = app(Sms::class)->where($where)->order('a_time desc')->find();
            if ($info && ($time - $info['a_time']) < 60) {
                throw new BusinessException('请求频率过快');
            }

            // OpenId最大发送量检测
            $where = [
                ['openid', '=', $openid],
                ['a_time', 'between', [$s_time, $e_time]],
            ];
            $count = app(Sms::class)->where($where)->count();
            if ($count >= 5) {
                throw new BusinessException('请求量超过最大阈值');
            }
        }
    }

    /**
     * sendCode
     * @throws
     */
    public function sendCode($mobile, $code, $ip, $openid = '')
    {
        // 构建记录
        $time = time();
        $record = [
            'mobile' => $mobile,
            'code' => $code,
            'ip' => $ip,
            'openid' => $openid,
            'response' => '',
            'a_time' => $time,
        ];

        // 发送短信
        try {

            $appId = getAppId();
            $config = app(AppConfig::class)->getByIdAndType($appId, 'think_sms_config');
            $client = new Client($config['token']);
            $result = $client->smsSend()
                ->withSignId($config['signId'])
                ->withTemplateId($config['templateId'])
                ->withPhone($mobile)
                ->withParams('{"code": "' . $code . '"}')
                ->request();

            // 检查结果
            if (!$result) {
                throw new BusinessException('发送失败，请联系客服');
            }

            // 保存到记录中
            $record['response'] = json_encode($result);

            // 提取状态
            $sendStatusSet = $result['code'];
            if ($sendStatusSet == -1) {
                throw new BusinessException('下发状态失败，请联系客服');
            }
        } catch (\Exception $e) {
            $record['send_status'] = 2;
            throw $e;
        } finally {
            $isInsert = app(Sms::class)->insert($record);
            if (!$isInsert) {
                throw new BusinessException('保存发送日志失败，请联系客服');
            }
        }
    }

    /**
     * checkCode
     * @param $mobile
     * @param $code
     * @return bool
     * @throws
     */
    public function checkCode($mobile, $code): bool
    {
        $time = time() - 3600;
        $where = [
            ['code', '=', $code],
            ['mobile', '=', $mobile],
            ['a_time', '>=', $time],
        ];
        return (bool)app(Sms::class)->where($where)->count();
    }
}